#ifndef AFCORE_COMMON_ASIOWRAP_ASIOWRAP_IPNETWORK_
#define AFCORE_COMMON_ASIOWRAP_ASIOWRAP_IPNETWORK_

#include <boost/asio/ip/network_v4.hpp>
#include <boost/asio/ip/network_v6.hpp>

#include "define.h"
#include "asiowrap_ipaddress.h"

namespace afcore {
namespace net {

inline boost::asio::ip::address_v4 GetDefaultNetmaskV4(const boost::asio::ip::address_v4& address_network) {
  if ((AddressV4ToUInt(address_network) & 0x80000000) == 0) {
    return boost::asio::ip::address_v4(0xFF000000);
  }
  if ((AddressV4ToUInt(address_network) & 0xC0000000) == 0x80000000) {
    return boost::asio::ip::address_v4(0xFFFF0000);
  }
  if ((AddressV4ToUInt(address_network) & 0xE0000000) == 0xC0000000) {
    return boost::asio::ip::address_v4(0xFFFFFF00);
  }
  return boost::asio::ip::address_v4(0xFFFFFFFF);
}


inline bool IsInNetwork(const boost::asio::ip::address_v4& address_network,
  const boost::asio::ip::address_v4& mask,
  const boost::asio::ip::address_v4& address_client) {
  boost::asio::ip::network_v4 network = boost::asio::ip::make_network_v4(address_network, mask);
  boost::asio::ip::address_v4_range hosts = network.hosts();
  return hosts.end() != hosts.find(address_client);
}

inline bool IsInNetwork(const boost::asio::ip::address_v6& address_network,
  uint16_t prefix_length,
  const boost::asio::ip::address_v6& address_client) {
  boost::asio::ip::network_v6 network = boost::asio::ip::make_network_v6(address_network, prefix_length);
  boost::asio::ip::address_v6_range hosts = network.hosts();
  return hosts.end() != hosts.find(address_client);
}

} // !namespace net
} // !namespace afcore

#endif //! AFCORE_COMMON_ASIOWRAP_ASIOWRAP_IPNETWORK_